Each instance of the audivolv.SimpleFuncInfo class describes some flo variables.
Some of them must stay in specific ranges, like -1 to 1, when an audivolv.Func runs.
The main problem is its inefficient to check if flos are in that range after every change.
AntiExample: "x += .01" could put x over 1 if x is .999
Example: "x = Math.sin(y*500)*.9 + .1*z;" is always in range -1 to 1 if y and z range -1 to 1.
Technically, Audivolv's design allows x y and z to exceed that range during the audivolv.Func call
if they are back in that range at the end of the call, but that complicates evolution of code
and should be avoided if code can be fast and flexible without exceeding that range.
In the worst case, the problem can be solved
by adding "x = Math.max(-1., Math.min(x, 1.));" after every change to x, but that is slow. 
Is there a faster solution thats also simple? I write about that in this file...
===============================================================================================

Maybe each flo code should be interpreted as a multi-dimensional cartesian-space,
ranging -1 to 1 in each dimension, and each dimension is 1 of the vars.
A function call starts at a single point in that hypercube and returns some point.
Exiting the hypercube is always an error (flo out of range).
It is hard to view it as a vector field because a function call is not continuous.
It is called or it is not, but linear interpolation between those 2 states is similar.
To evolve good flo code, test each code at many points in the hypercube,
and in each test, do a million function calls, which each can move the point,
and verify the point never exits the hypercube.
In that way, learn which parts of the hypercube eventually lead to error,
and say its an error if any other test leads to any of the known error areas.
Its like a fractal calculation, always getting a more accurate picture of the fractal.


CALCULUS:
Its not calculus because time is in integer units, but I will write it as calculus this way:
All letters f-z are vars. All vars plus a base-10 nonnegative integer are vars. Example: f0, z9, f30.
t is the time var which increases with each audivolv.Func call.
Hypercube means all combinations of possible values of multiple vars, usually each var ranging -1 to 1.
Point (in a hypercube) means 1 specific value for each of multiple vars.
x=y means to change the value of x to the value of y, which is moving in a hypercube.
x==y means to measure if they are equal and say true or false.
d means calculus-derivative.
dx means the change in x when t increases by 1, unless t is written in some other way,
but increasing t by 1 contradicts the continuous nature of calculus, so this system is not perfect.
Other imperfection: flo is a 64-bit floating point number so there is roundoff error.
/ is divide.
dx is abbrev of dx/dt.
dy/dx is a derivative of y relative to x.

If y is only an input var and x is only an output var, then dy is 0 and dx depends on dy.
There is another variable, the counterpart of t: i. i is input to the audivolv.Func and t is output.
Rename t to o because t is output.
Audivolv alternates i o i o i o... within a hypercube, running the same audivolv.Func.
Each o is what results from running i, and that o becomes the next i.

The purpose of this calculus-like system of writing is to design audivolv.Func that
always end in the hypercube if they start anywhere in the hypercube, which requires that
anything leaving the hypercube must go back into it before the audivolv.Func ends.
An easy way to do that is for all points in the hypercube to flow toward a smaller area
in the hypercube, but not to shrink past that constant size area even after millions of calls.

Hypercubes could be compared to eachother by aligning on any reordering or renaming of their dimensions.
Example: "x = x / (1.1*y);" is useful to combine with "c = c * 1.05 * x;" if viewed as "x = x * 1.05 * y;".
By itself, "x = x * 1.05 * y;" is divergent and can not be used except at x==0 and/or y==0,
but when combined with "x = x / (1.1*y);", it becomes convergent therefore useable.
Convergent things are usable but often are not useful because they converge to a constant like 0.
Why not just write 0 into the code and leave it there? They are only useful in combination with other code.

This calculus/hypercube system could be much more useful than random evolution of code strings
because random code often converges to a constant, causing audio data to be silent if its audio code.
Code represented as hypercubes could be evolved to keep points moving in the hypercube
and to avoid points leaving the hypercube unless they will come back into the hypercube.

AFTER THINKING MORE ABOUT THE HYPERCUBE DESIGN, THE EXACT DESIGN IS:

All hypercube operators are audivolv.Func, and they can do 1 time step forward (like a normal function)
or 1 time step backward, or anything between (like in calculus).
Example: a hypercube of t (time var), x (normal var), and y (normal var) that rotates x and y
in a circle of constant radius counterclockwise.
Its an audivolv.Func with 3 flo vars at indexs 0 (time) 1 (x) and 2 (y).
For any hypercube func, if t is 0 then running the func changes no flos.
In this circle func, set t to 1, and x and y will go partially around the circle.
How far around the circle can be different for each func.
It could even go faster in some parts of the circle than others, but it must consistently do that.
If Math.sqrt(x*x+y*y) > 1, the circle is not possible so it must move somewhere else.
If Math.sqrt(x*x+y*y) <= 1, and you set t to -.4 and run it, it moves x and y clockwise .4*someConstant
amount, and sets t to 0.
Running the func, for any in-range flo values of any of the vars, always sets t to 0.
That is because time is always relative to "now" and you can not directly go to the past or future.
If after that t=-.4 call you keep the resulting x and y and set t to .2 and run it, and do the same again,
x and y should be at their original positions before the t=-.4 call, and of course t becomes 0.
This circle audivolv.Func is consistent because setting t to any value ranging -1 to 1
results in the same x and y values as if you did multiple calls with t values summing to
the same original t, but not all hypercube audivolv.Func have to be that way.
Some hypercube audivolv.Func can be approximations to that but slowly diverge because of
the difference between discrete function calls and continuous calculus.
Example: if x and y are both .5, then x may become .4 and y become .6 because thats
the direction of the calculus derivatives dx/dt and dy/dt. It ignores that the
derivative changes as t increases. Its an approximation, and its ok for some
hypercube audivolv.Funcs to do that.
The requirement of all vars to stay in range -1 to 1 is strict, but consistency
of summing many t vs 1 bigger t is allowed to be approximate.

Example: an IF statement can be like multiply.
"ifFunc(xFunc) yFunc; else zFunc"
Can be this instead:
"ifFunc = (.5+.5*xFunc)*yFunc + (.5-.5*xFunc)*zFunc;"
If xFunc is -1, yFunc has no effect so theoretically would not be called, and zFunc would be used.
If xFunc is 1,  the opposite happens.
If xFunc is between -1 and 1 but not equal to -1 or 1, yFunc and zFunc must be run.

Any logic can be implemented as a hypercube audivolv.Func this way.
The EQUALS operator takes 3 parameters: t, x, y.
"x = y" with t==.1 would have this effect: x = .9*x + .1*y;
The code is: x = (1-t)*x + t*y;
With t=-1, the effect is invalid: x = (1-(-1))*x + (-1)*y;
"x = 2*x - y" is invalid because it exceeds range -1 to 1 for some values of x and y.

For the EQUALS operator, t can not be negative.
Should it instead set y=x instead of x=y if its negative? It makes sense, but its slower.
if(t > 0){
	x = (1-t)*x + t*y;
}else{
	y = (1-(-t))*y + (-t)*x;
}

Its more efficient to define it this way:
if(t == 1){
	x = y;
}else if(t == -1){
	y = x;
}else if(t > 0){
	x = (1-t)*x + t*y;
}else{
	y = (1+t)*y - t*x;
}

If all logic is reversible like this, advanced things could be done,
assuming roundoff error and calculus-discrete-approximations are small.

"x = y * z;" is a 4 dimensional hypercube func.

"x = y / z;" is only valid when Math.abs(y) <= Math.abs(z).
How can divide be represented?
Does it always have to include a number to make it smaller?:
"x = .001*y/z;" works for almost all values of y and z in range -1 to 1, but some will always be invalid,
so different behavior for those cases must be defined.


Given many hypercube funcs, some will be combined, and there are at least 2 main ways to do that:
(1) In sequence of b number of funcs, setting t to tOriginalValue/b before each.
(2) Parallel run b number of funcs from the same starting values of all vars, and (weighted?) average them.
And a third more dangerous way:
(3) Read/write the value of t in some of the funcs, like a sequence5 func called with t==.3
would store .3 and set t to .3/5 before calling each of 3 funcs, and would not change any other vars. 